<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Exceptions\CommonExceptionConstants;
use App\Exceptions\ServiceException;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Str;

class Controller extends BaseController
{
    use AuthorizesRequests;
    use DispatchesJobs;
    use ValidatesRequests;

    // 解析出模型名称，规则为 SystemController 解析为 System
    private $modelName;
    // 文件路径前缀
    private $path;
    // 命名空间前缀
    private $namespace;
    // 如果为插件当前插件的名称
    private $addonName;

    public function __construct()
    {
        $this->initialize();
    }

    /**
     * 根据控制器名称按照约定获取到table名称.
     *
     * @param mixed $isComplex 是否将表名称转换为复数形式
     *
     * @return string
     */
    protected function getModel($isComplex = true): string
    {
        // 如果设置了model 则直接使用
        if (property_exists($this, 'model')) {
            return $this->model;
        }
        // 获取model的命名空间
        $namespaceName = $this->getNamespaceName($this->getModelName());

        return $namespaceName ?? ($isComplex ? Str::plural($this->getModelName()) : $this->getModelName());
    }

    protected function getModelName(): string
    {
        return $this->modelName;
    }

    protected function getPath()
    {
        return $this->path;
    }

    protected function getNamespace()
    {
        return $this->namespace;
    }

    protected function getAddonName()
    {
        return $this->addonName;
    }

    protected function getNamespaceName($modelName, $folder = 'Models'): ?string
    {
        $fileName = $modelName.'.php';
        $name = $this->getNamespace().'\\'.Str::replace(\DIRECTORY_SEPARATOR, '\\', $folder).'\\'.$modelName;
        $path = $this->getPath().\DIRECTORY_SEPARATOR.$folder.\DIRECTORY_SEPARATOR.$fileName;
        $path = base_path($path);

        return file_exists($path) ? $name : null;
    }

    /**
     * 实现通过路由传参和get参数.
     *
     * @return array
     */
    protected function getIds(): array
    {
        $id = request()->route('id');
        $ids = normIds(request()->get('ids'));
        if ($id) {
            $ids[] = $id;
        }
        if (0 === \count($ids)) {
            throw new ServiceException(CommonExceptionConstants::ERROR_PARAM);
        }

        return $ids;
    }

    private function initialize(): void
    {
        $className = explode('\\', static::class);
        $modelName = Str::before(array_pop($className), 'Controller');
        $this->modelName = ucfirst($modelName);
        if ('App' === reset($className)) {
            $this->path = 'app';
            $this->namespace = 'App';
        } else {
            $addon = $className[1] ?? '';
            $this->path = 'app'.\DIRECTORY_SEPARATOR.$addon;
            $this->namespace = 'Addon\\'.ucfirst($addon);
            $this->addonName = $addon;
        }
    }
}
